﻿using System;
using System.Collections.Generic;
using System.Linq;

namespace ComponentSystem
{
    /// <summary>
    /// CSharp 实体
    /// </summary>
    public partial class EntityCSharp : ComponentWithId
    {
        /// <summary>
        /// 如果是使用 父Mono实体来创建，则需要保存父Mono实体
        /// </summary>
        protected EntityMono parentMono { get; set; }

        /// <summary>
        /// 组件集合
        /// </summary>
        private HashSet<Component> components;

        /// <summary>
        /// 组件字典
        /// </summary>
        private Dictionary<Type, Component> componentDict;
    }

    public partial class EntityCSharp
    {
        public EntityCSharp() : base()
        {

        }

        /// <summary>
        /// 带ID构造函数
        /// </summary>
        public EntityCSharp(long id) : base(id)
        {

        }

        /// <summary>
        /// 构造函数
        /// </summary>
        protected override void Constructor()
        {
            this.components = new HashSet<Component>();
            this.componentDict = new Dictionary<Type, Component>();

            base.Constructor();
        }

        /// <summary>
        /// 带ID构造函数
        /// </summary>
        protected override void Constructor(long id)
        {
            this.components = new HashSet<Component>();
            this.componentDict = new Dictionary<Type, Component>();
            base.Constructor(id);
        }

        #region 父Mono实体相关函数

        /// <summary>
        /// 获取父组件 泛型
        /// </summary>
        public T GetParentMono<T>() where T : EntityMono
        {
            return this.parentMono as T;
        }

        /// <summary>
        /// 获取父Mono实体
        /// </summary>
        public EntityMono EntityMono
        {
            get
            {
                return this.parentMono as EntityMono;
            }
        }

        /// <summary>
        /// 更新父Mono实体
        /// </summary>
        public EntityMono UpdateParentMono(EntityMono parentMono)
        {
            this.parentMono = parentMono;
            return this.parentMono;
        }

        #endregion

        /// <summary>
        /// 是否包含组件
        /// </summary>
        public virtual bool HasComponent(Component component)
        {
            Type type = component.GetType();
            if (this.componentDict.ContainsKey(type))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 是否包含组件
        /// </summary>
        public virtual bool HasComponent(Type type)
        {
            if (this.componentDict.ContainsKey(type))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 是否包含组件
        /// </summary>
        public virtual bool HasComponent<T>()
        {
            Type type = typeof(T);
            if (this.componentDict.ContainsKey(type))
            {
                return true;
            }

            return false;
        }

        /// <summary>
        /// 添加组件
        /// </summary>
        public virtual Component AddComponent(Component component)
        {
            Type type = component.GetType();
            if (this.componentDict.ContainsKey(type))
            {
                throw new Exception($"AddComponent, component already exist, id: {this.InstanceId}, component: {type.Name}");
            }

            component.Parent = this;

            if (component is ISerializeToEntity)
            {
                this.components.Add(component);
            }
            this.componentDict.Add(type, component);
            return component;
        }

        /// <summary>
        /// 添加组件
        /// </summary>
        public virtual Component AddComponent(Type type)
        {
            if (this.componentDict.ContainsKey(type))
            {
                throw new Exception($"AddComponent, component already exist, id: {this.InstanceId}, component: {type.Name}");
            }

            Component component = ComponentFactory.CreateWithParent(type, this);

            if (component is ISerializeToEntity)
            {
                this.components.Add(component);
            }
            this.componentDict.Add(type, component);
            return component;
        }

        /// <summary>
        /// 添加组件
        /// </summary>
        public virtual K AddComponent<K>() where K : Component, new()
        {
            Type type = typeof(K);
            if (this.componentDict.ContainsKey(type))
            {
                throw new Exception($"AddComponent, component already exist, id: {this.InstanceId}, component: {typeof(K).Name}");
            }

            K component = ComponentFactory.CreateWithParent<K>(this);

            if (component is ISerializeToEntity)
            {
                this.components.Add(component);
            }
            this.componentDict.Add(type, component);
            return component;
        }

        /// <summary>
        /// 移除组件
        /// </summary>
        public virtual void RemoveComponent<K>() where K : Component
        {
            Type type = typeof(K);
            Component component;
            if (!this.componentDict.TryGetValue(type, out component))
            {
                return;
            }

            this.components.Remove(component);
            this.componentDict.Remove(type);

            component.Dispose();
        }

        /// <summary>
        /// 移除组件
        /// </summary>
        public virtual void RemoveComponent(Type type)
        {
            Component component;
            if (!this.componentDict.TryGetValue(type, out component))
            {
                return;
            }

            this.components?.Remove(component);
            this.componentDict.Remove(type);

            component.Dispose();
        }

        /// <summary>
        /// 获取组件
        /// </summary>
        public K GetComponent<K>() where K : Component
        {
            Component component;
            if (!this.componentDict.TryGetValue(typeof(K), out component))
            {
                return default(K);
            }
            return (K)component;
        }

        /// <summary>
        /// 获取组件
        /// </summary>
        public Component GetComponent(Type type)
        {
            Component component;
            if (!this.componentDict.TryGetValue(type, out component))
            {
                return null;
            }
            return component;
        }

        /// <summary>
        /// 获取组件
        /// </summary>
        public K GetComponentOrAdd<K>() where K : Component, new()
        {
            if (this.HasComponent<K>())
            {
                return this.GetComponent<K>();
            }
            else
            {
                return this.AddComponent<K>();
            }
        }

        /// <summary>
        /// 获取组件
        /// </summary>
        public Component[] GetComponents()
        {
            return this.componentDict.Values.ToArray();
        }

        #region 状态管理
        /// <summary>
        /// 重新开始
        /// </summary>
        public override void ReStart()
        {
            if (this.IsStart())
            {
                return;
            }
            base.ReStart();
            //跟新所有子组建
            foreach (Component component in this.componentDict.Values)
            {
                component.ReStart();
            }
        }
        /// <summary>
        /// 停止
        /// </summary>
        public override void Stop()
        {
            if (this.IsStop())
            {
                return;
            }
            base.Stop();
            //跟新所有子组建
            foreach (Component component in this.componentDict.Values)
            {
                component.Stop();
            }
        }
        /// <summary>
        /// 暂停
        /// </summary>
        public override void Pause()
        {
            if (this.IsPause())
            {
                return;
            }
            base.Pause();
            //跟新所有子组建
            foreach (Component component in this.componentDict.Values)
            {
                component.Pause();
            }
        }
        /// <summary>
        /// 恢复
        /// </summary>
        public override void Resume()
        {
            if (this.IsResume())
            {
                return;
            }
            base.Resume();
            //跟新所有子组建
            foreach (Component component in this.componentDict.Values)
            {
                component.Resume();
            }
        }

        /// <summary>
        /// 重置
        /// </summary>
        public override void Reset()
        {
            if (this.IsReset())
            {
                return;
            }
            base.Reset();
            //跟新所有子组建
            foreach (Component component in this.componentDict.Values)
            {
                component.Reset();
            }
        }

        /// <summary>
        /// 销毁
        /// </summary>
        public override void Dispose()
        {
            if (this.IsDisposed())
            {
                return;
            }

            base.Dispose();

            foreach (Component component in this.componentDict.Values)
            {
                try
                {
                    component.Dispose();
                }
                catch (Exception e)
                {
                    UnityEngine.Debug.LogError(e);
                }
            }

            this.components.Clear();
            this.componentDict.Clear();

        }

        #endregion
    }
}